Skip to content

Conversation

@JonathanOppenheimer
Copy link
Member

@JonathanOppenheimer JonathanOppenheimer commented Dec 22, 2025

Why this should be merged

The subnet-evm rpc package was practically identical to the coreth rpc package. It makes no sense to maintain two copies of this code. This also makes moving to libevm's rpc package far easier, to look in one location and see what needs to be libevmified.

How this works

  • Created graft/evm/rpc/ directory structure
  • Copied all source files from coreth/rpc to the shared location
  • Updated graft/evm/go.mod with required dependencies:
    • github.com/gorilla/websocket v1.5.0
    • github.com/deckarep/golang-set/v2 v2.1.0
    • golang.org/x/time v0.12.0
  • Fixed test imports and restored TestNotify to original libevm version
  • Removed test_main.go for registration during testing.
Outdated information I also added `main_test.go` with a `TestMain` that automatically runs all RPC tests twice - once with C-Chain type registration and once with Subnet-EVM type registration.

This works by putting TestMain in package rpc_test (an external test package) instead of package rpc, which lets us import the emulate package without creating a circular dependency. We can then use emulate.CChain() and emulate.SubnetEVM() to properly register/cleanup types between test runs.

Thus when you run go test (which also automatically happens via CI -- you can check for yourself!), it:

  1. Runs all tests with C-Chain types registered via emulate.CChain()
  2. Cleans up the registration
  3. Runs all tests again with Subnet-EVM types via emulate.SubnetEVM()
  4. Reports if either variant fails

How this was tested

CI

Need to be documented in RELEASES.md?

No

@JonathanOppenheimer JonathanOppenheimer self-assigned this Dec 22, 2025
@JonathanOppenheimer JonathanOppenheimer added cleanup Code quality improvement evm Related to EVM functionality labels Dec 22, 2025
@JonathanOppenheimer JonathanOppenheimer marked this pull request as ready for review December 22, 2025 18:55
@JonathanOppenheimer JonathanOppenheimer requested a review from a team as a code owner December 22, 2025 18:55
Copy link
Contributor

@alarso16 alarso16 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to register the types for our tests? I think that was the only thing preventing us from using the geth rpc package

@JonathanOppenheimer
Copy link
Member Author

JonathanOppenheimer commented Dec 29, 2025

Don't we need to register the types for our tests? I think that was the only thing preventing us from using the geth rpc package

The only place we registered was in an additional main file just in subnet-evm, and that was for test retrying for flakes. I removed that as we should not be doing test retries in the monorepo, and should just skip flaky tests entirely if they're flaky. Is there registration anywhere else?

@alarso16
Copy link
Contributor

Don't we need to register the types for our tests? I think that was the only thing preventing us from using the geth rpc package

The only place we registered was in an additional main file just in subnet-evm, and that was for test retrying for flakes. I removed that as we should not be doing test retries in the monorepo, and should just skip flaky tests entirely if they're flaky. Is there registration anywhere else?

No, we didn't just retry failed tests. They also registered customtypes in each respective repo, so that's why the contents of the block changed when you moved them over. I'm not sure if we still need to be testing that functionality

@JonathanOppenheimer
Copy link
Member Author

JonathanOppenheimer commented Dec 31, 2025

Don't we need to register the types for our tests? I think that was the only thing preventing us from using the geth rpc package

The only place we registered was in an additional main file just in subnet-evm, and that was for test retrying for flakes. I removed that as we should not be doing test retries in the monorepo, and should just skip flaky tests entirely if they're flaky. Is there registration anywhere else?

No, we didn't just retry failed tests. They also registered customtypes in each respective repo, so that's why the contents of the block changed when you moved them over. I'm not sure if we still need to be testing that functionality

I don't think this is true. There are two places in this PR where I removed customtypes.Register().

  1. For a test retry loop. As explained above, I this this is unnecessary.
  2. In TestMain of subnet-evm's subscription test. This differed from coreth, and only appeared to be present as we were still importing the old custom types instead of the libevm types package. I removed it to align the two, as I assume subnet-evm just didn't get updated.

Are there other important places in which I removed it?

@ARR4N
Copy link
Contributor

ARR4N commented Jan 2, 2026

If customtypes.Register() isn't called then the test isn't testing coreth / subnet-evm functionality in its entirety. I'd recommend using evm.RegisterLibEVMExtras() (which calls customtypes.Register()) instead of the individual registration as this guarantees that all hooks/payloads are registered.

This can alternately be done with emulate.CChain() and emulate.SubnetEVM() if you need to test both in the same package (i.e. the same test binary). If there is commonality between the testing then the best approach is probably something like:

func testCChainAndSubnetEVM(t *testing.T, testFn func(*testing.T)) {
  fn := func() error {
    testFn(t)
    return nil
  }

  t.Run("cchain", func(t *testing.T) {
    _ = emulate.CChain(fn)
  })
  t.Run("subnetEVM", func(t *testing.T) {
    _ = emulate.SubnetEVM(fn)
  })
}

func TestFoo(t *testing.T) {
  testCorethAndSubnetEVM(t, testFoo)
}

func testFoo(t *testing.T) {
  // this is where the actual testing occurs; i.e. just rename any existing TestFoo to testFoo
}

func TestBar(t *testing.T) {
  testCorethAndSubnetEVM(t, testBar)
}

func testBar(t *testing.T) {
  // as with testFoo()
}

The linter is going to tell you to call t.Helper() but it's better not to in this case otherwise all errors will be reported as being on the single line of the TestFoo() implementation, instead of on the specific line in testFoo().

@alarso16
Copy link
Contributor

alarso16 commented Jan 2, 2026

I believe we have decided to enforce that we don't want cyclic dependencies between coreth and evm, so we would probably have to "uplift" the customtypes packages first. Also, I have tried this in #4688, and trying to register all EVM imports in this package causes a cyclic dependency (unless you make a test package?)

@JonathanOppenheimer
Copy link
Member Author

JonathanOppenheimer commented Jan 2, 2026

I believe we have decided to enforce that we don't want cyclic dependencies between coreth and evm, so we would probably have to "uplift" the customtypes packages first. Also, I have tried this in #4688, and trying to register all EVM imports in this package causes a cyclic dependency (unless you make a test package?)

Yeah I am trying this right now and was about to comment about the cyclic imports. The shared graft/evm/rpc package is a dependency used by coreth, which creates a circular dependency if we try to use vms/evm/emulate (which depends on coreth) in the RPC tests. This can be avoided if we just call the custom types registration directly or put it in a seperate test package.

I definitely think this + in conjunction with some sort of test main would be a good model for how to combine packages while testing separately. I've committed a new main_test.go which does this to some extent although simpler. What are the thoughts on this approach?

@JonathanOppenheimer JonathanOppenheimer added the testing This primarily focuses on testing label Jan 2, 2026
notifier.Notify(id, msg)
have := strings.TrimSpace(out.String())
want := `{"jsonrpc":"2.0","method":"_subscription","params":{"subscription":"test","result":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000001","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":null,"number":"0x64","gasLimit":"0x0","gasUsed":"0x0","timestamp":"0x0","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","extDataHash":"0x0000000000000000000000000000000000000000000000000000000000000000","baseFeePerGas":null,"extDataGasUsed":null,"blockGasCost":null,"blobGasUsed":null,"excessBlobGas":null,"parentBeaconBlockRoot":null,"timestampMilliseconds":null,"minDelayExcess":null,"hash":"0x9a9ca1b5790a674785245afedcee9fc1a90d3514c6faa1cbd26f696136d6fd12"}}}`
want := `{"jsonrpc":"2.0","method":"_subscription","params":{"subscription":"test","result":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000001","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":null,"number":"0x64","gasLimit":"0x0","gasUsed":"0x0","timestamp":"0x0","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":null,"withdrawalsRoot":null,"blobGasUsed":null,"excessBlobGas":null,"parentBeaconBlockRoot":null,"hash":"0xe5fb877dde471b45b9742bb4bb4b3d74a761e2fb7cb849a3d2b687eed90fb604"}}}`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ceyonur suggested bring back the original TestNotify, rather than deleting it entirely, when testing without registration.

@@ -9,7 +9,7 @@
//
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub is drunk showing this move...

@JonathanOppenheimer
Copy link
Member Author

After extensive discussion, we have decided not to test under registration.

JonathanOppenheimer and others added 2 commits January 21, 2026 15:36
Co-authored-by: Austin Larson <[email protected]>
Signed-off-by: Jonathan Oppenheimer <[email protected]>
Copy link
Contributor

@alarso16 alarso16 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The go.mod changes are somewhat suspicious, but I don't think an actual issue

@JonathanOppenheimer JonathanOppenheimer removed the request for review from ARR4N January 21, 2026 21:01
@JonathanOppenheimer JonathanOppenheimer removed the request for review from a team January 21, 2026 21:08
Copy link
Contributor

@ceyonur ceyonur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

@ceyonur ceyonur added this pull request to the merge queue Jan 23, 2026
Merged via the queue into master with commit d6b693c Jan 23, 2026
53 checks passed
@ceyonur ceyonur deleted the JonathanOppenheimer/share-rpc-package branch January 23, 2026 18:52
@github-project-automation github-project-automation bot moved this to Done 🎉 in avalanchego Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cleanup Code quality improvement evm Related to EVM functionality testing This primarily focuses on testing

Projects

Status: Done 🎉

Development

Successfully merging this pull request may close these issues.

6 participants